using System;
using WCell.Constants;
using WCell.Constants.World;
using WCell.Core.Network;
using WCell.RealmServer.Entities;
using WCell.RealmServer.Network;

namespace WCell.RealmServer.Handlers
{
	public class InstanceHandler
	{
		#region Handling
		[ClientPacketHandler(RealmServerOpCode.CMSG_RESET_INSTANCES)]
		public static void HandleInstanceReset(IRealmClient client, RealmPacketIn packet)
		{
			if (client.ActiveCharacter != null && client.ActiveCharacter.HasInstanceCollection)
			{
				client.ActiveCharacter.Instances.ResetInstances();
			}
		}

		[ClientPacketHandler(RealmServerOpCode.CMSG_REQUEST_RAID_INFO)]
		public static void RequestRaidInfo(IRealmClient client, RealmPacketIn packet)
		{
			SendRaidInfo(client.ActiveCharacter);
		}

        [ClientPacketHandler(RealmServerOpCode.MSG_SET_RAID_DIFFICULTY)]
        public static void SetRaidDifficulty(IRealmClient client, RealmPacketIn packet)
        {
            var mode = packet.ReadUInt32();
            // TODO: set difficulty
        }

		#endregion


		#region Send
		public static void SendInstanceReset(IPacketReceiver client, MapId mapId)
		{

		}

		public static void SendInstanceSave(IPacketReceiver client, MapId mapId)
		{
			using (var packet = new RealmPacketOut(RealmServerOpCode.SMSG_UPDATE_LAST_INSTANCE,4))
			{
				packet.Write((int)mapId);
				client.Send(packet);
			}
		}

		public static void SendRequiresRaid(IRealmClient client)
		{
			using (RealmPacketOut packet = new RealmPacketOut(RealmServerOpCode.SMSG_RAID_GROUP_ONLY, 8))
			{
				packet.WriteInt(0);
				packet.WriteInt(1);
				client.Send(packet);
			}
		}

		/// <summary>
		/// Creates a countdown timer that will count down to 0
		/// </summary>
		/// <param name="client"></param>
		/// <param name="time"></param>
		public static void SendRemovalWarning(IPacketReceiver client, int time)
		{
			using (RealmPacketOut packet = new RealmPacketOut(RealmServerOpCode.SMSG_RAID_GROUP_ONLY, 8))
			{
				packet.WriteInt(time);
				packet.WriteInt(1);
				client.Send(packet);
			}
		}

		public static void SendRaidInfo(Character chr)
		{
			using (var packet = new RealmPacketOut(RealmServerOpCode.SMSG_RAID_INSTANCE_INFO))
			{
				if (chr.HasInstanceCollection)
				{
					packet.Position += 4;
					uint count = 0;
					foreach (var instance in chr.Instances)
					{
						if (!instance.Expires)
						{
							continue;
						}

						var timeLeft = instance.ExpiryTime - DateTime.Now;
						if (timeLeft.Ticks > 0)
						{
							count++;
							packet.Write((uint)instance.RegionId);
                            packet.WriteUInt(0); // this is difficulty.
							packet.Write(instance.InstanceId);
                            packet.WriteByte(0x1); // expired = 0
                            packet.WriteByte(0x0); // extended = 1
                            packet.Write((uint)timeLeft.TotalSeconds);
                            //packet.Write(0); // unk, extended?
						}
					}
					packet.Position = packet.HeaderSize;
					packet.Write(count);
				}
				else
				{
					packet.Write(0);
				}

				chr.Client.Send(packet);
			}
		}
		/// <summary>
		/// Sends the result of an instance reset attempt
		/// </summary>
		/// <param name="client"></param>
		/// <param name="reason"></param>
		public static void SendResetFailure(IPacketReceiver client, MapId map, InstanceResetFailed reason)
		{
			using (var packet = new RealmPacketOut(RealmServerOpCode.SMSG_INSTANCE_RESET_FAILED, 5))
			{
				packet.WriteUInt((uint)map);
				packet.WriteUInt((uint)reason);
				client.Send(packet);
			}
		}

		/// <summary>
		/// Warns a player within the instance that the leader is attempting to reset the instance
		/// </summary>
		/// <param name="client"></param>
		public static void SendResetWarning(IPacketReceiver client)
		{
			using (var packet = new RealmPacketOut(RealmServerOpCode.SMSG_RESET_FAILED_NOTIFY, 5))
			{
				client.Send(packet);
			}
		}

		public static void SendTransferFailure(IPacketReceiver client, MapId mapId, InstanceTransferFailed reason)
		{
			using (var packet = new RealmPacketOut(RealmServerOpCode.SMSG_TRANSFER_ABORTED, 8))
			{
				packet.WriteInt((int)mapId);
				packet.WriteInt((int)reason);
				client.Send(packet);
			}
		}
		#endregion
	}
}
